#coding=utf-8
import sys
import os
import pygame
from time import sleep
from bullet import Bullet
from alien import Alien
import threading
import copy


def check_events(setting, screen, stats, ship, aliens, bullets, sb,
                 play_button, path):
    '''监听鼠标键盘事件'''
    for event in pygame.event.get():
        if event.type == pygame.QUIT:  #接收到关闭命令是关闭程序
            os._exit(0)
        elif event.type == pygame.KEYDOWN:  #键盘按下事件
            check_keydown_events(event, setting, screen, stats, ship, sb,
                                 bullets, aliens, path)
        elif event.type == pygame.KEYUP:  #键盘弹起事件
            check_keyup_events(event, setting, screen, ship, bullets)
        elif event.type == pygame.MOUSEBUTTONDOWN:
            #返回一个鼠标点击位置的元组,元组可以单独赋值
            mouse_x, mouse_y = pygame.mouse.get_pos()
            check_play_button(setting, screen, stats, aliens, ship, bullets,
                              sb, path, play_button, mouse_x, mouse_y)


def check_play_button(setting, screen, stats, aliens, ship, bullets, sb, path,
                      play_button, mouse_x, mouse_y):
    '''鼠标单击PLAY按钮是开始新游戏'''
    #判断x,y是否在rect中
    button_clicked = play_button.rect.collidepoint(mouse_x, mouse_y)
    if button_clicked and (not stats.game_active):
        #重置内容
        stat_game(setting, screen, stats, aliens, ship, sb, bullets, path)


def stat_game(setting, screen, stats, aliens, ship, sb, bullets, path):
    '''开始游戏'''
    #重置内容
    stats.reset_stats()  #回生命数及其他初始设置
    stats.game_active = True  #允许游戏开始

    #清空外星人和子弹列表
    aliens.empty()
    bullets.empty()
    #创建一群新的外星人，并将飞船放到屏幕底端中央
    create_fleet(setting, screen, aliens, ship, path)
    ship.center_ship()

    #重置游戏设置
    setting.initialize_dynamic_settings()
    sb.prep_score()  #更新分数数据
    sb.prep_level()  #更新等级数据
    sb.prep_ships()  #更新左上角生命数

    #隐藏光标
    pygame.mouse.set_visible(False)


def check_keydown_events(event, setting, screen, stats, ship, sb, bullets,
                         aliens, path):
    '''响应键盘按下'''
    #游戏没有暂停的时候才能响应的事
    if not setting.stop:
        if event.key == pygame.K_RIGHT:  #按下右键
            ship.moving_right = True
            ship.moving_left = False
        elif event.key == pygame.K_LEFT:  #按下左键
            ship.moving_left = True
            ship.moving_right = False
        elif event.key == pygame.K_SPACE:  #按下空格射击
            if stats.game_active:
                fire_bullet(setting, screen, ship, bullets)  #飞船发射子弹
        elif event.key == pygame.K_k:
            if not stats.game_active:
                stat_game(setting, screen, stats, aliens, ship, sb, bullets,
                          path)


def check_keyup_events(event, setting, screen, ship, bullets):
    '''响应键盘弹起'''
    #游戏没有暂停的时候才能响应的事
    if not setting.stop:
        if event.key == pygame.K_RIGHT:  #弹起右键
            ship.moving_right = False
        elif event.key == pygame.K_LEFT:  #弹起左键
            ship.moving_left = False


def fire_bullet(setting, screen, ship, bullets):
    '''发射子弹事件'''
    #创建一颗子弹，并加入到编组bullets（Group）
    if len(bullets
           ) < setting.bullets_allowed:  #限制屏幕子弹数量 len()比限制数少1的时候触发一次，就和限制数一致了
        new_bullet = Bullet(setting, screen, ship)
        bullets.add(new_bullet)


def create_fleet(setting, screen, aliens, ship, path):
    '''创建外星人群'''
    #创建一个外星人，并及时一行可容纳多少个外星人
    alien = Alien(setting, screen, path)
    number_aliens_x = get_number_aliens_x(setting, alien.rect.width)  #一行外星人的数量
    number_aliens_y = get_number_aliens_y(setting, alien.rect.height,
                                          ship.rect.height)  #一列外星人的数量
    for alien_rownumber in range(number_aliens_y - 1):  #减一行
        for alien_number in range(number_aliens_x - 2):  #减两列
            create_alien(setting, screen, aliens, alien_number,
                         alien_rownumber, path)


def get_number_aliens_x(setting, alien_width):
    '''计算一行可以放几个外星人'''
    #一行外星人的宽,左右各留下一个外星人宽度的间隔
    available_space_x = setting.screen_width - 2 * alien_width
    #外星人间距为外星人宽度
    number_aliens_x = int(available_space_x / (2 * alien_width))  #一行能容纳的外星人数量
    return number_aliens_x


def get_number_aliens_y(setting, alien_height, ship_height):
    '''计算一列可以放几行外星人'''
    #一列外星人的高,顶上一个外星人高度（在外星人初始设置中写的）
    #底下一个飞船的高度，中间空白间隔3个外星人高度
    available_space_y = setting.screen_height - ship_height - 4 * alien_height
    #列间隔一个外星人的高度
    number_aliens_y = int(available_space_y / (2 * alien_height))
    return number_aliens_y


def create_alien(setting, screen, aliens, alien_number, alien_rownumber, path):
    '''创建一个外星人并加入到精灵组中'''
    alien = Alien(setting, screen, path)
    alien_width = alien.rect.width
    alien.x = alien_width * 3 + 2 * alien_width * alien_number  #离左边的距离
    alien.rect.x = alien.x
    alien.rect.y = alien.rect.height + 2 * alien.rect.height * alien_rownumber + 20  #离顶部的距离
    aliens.add(alien)


def check_fleet_edges(setting, aliens):
    '''有外星人达到边缘时采取相应的措施'''
    for alien in aliens.sprites():
        if alien.check_edges():
            change_fleet_direction(setting, aliens)
            break


def change_fleet_direction(setting, aliens):
    '''每个外星人下移并改变方向'''
    for alien in aliens.sprites():
        alien.rect.y += setting.alien_drop_speed
    setting.fleet_direction *= -1


def update_aliens(setting, stats, screen, ship, aliens, bullets, sb, path):
    '''更新所有外星人位置'''
    #检查每个外星人是否撞墙，有就下移和换方向
    check_fleet_edges(setting, aliens)
    aliens.update()
    #spritecollideany遍历精灵组，并返回第一个与单独精灵碰撞的精灵
    if pygame.sprite.spritecollideany(ship, aliens):
        ship_hit(setting, stats, screen, ship, aliens, bullets, sb, path)
    #检查是否有外星人到达屏幕底端
    check_aliens_bottom(setting, stats, screen, ship, aliens, bullets, sb,
                        path)


def update_bullet(setting, screen, stats, ship, aliens, bullets, sb, path):
    '''更新子弹数据'''
    bullets.update()
    '''删除超过上方屏幕的子弹'''
    for bullet in bullets:
        if bullet.rect.bottom <= 0:
            bullets.remove(bullet)

    check_bullet_alien_collisions(setting, screen, stats, ship, aliens,
                                  bullets, sb, path)


def check_bullet_alien_collisions(setting, screen, stats, ship, aliens,
                                  bullets, sb, path):
    '''检查是否有子弹击中外星人'''
    #击中就删除子弹和外星人
    #第一个True删除aliens , 第二个True上次bullets
    #放回的是字典，键是bullets值是aliens,碰撞时是否消失,第一个子弹第二个外星人
    collisions = pygame.sprite.groupcollide(bullets, aliens, True, True)
    if collisions:
        for value in collisions.values():
            for scr in value:
                stats.score += setting.alien_points
                sb.prep_score()
                check_high_score(stats, sb)

    #没有外星人了
    if len(aliens) == 0:
        #删除所有子弹，并创建一个新外星人群
        bullets.empty()
        setting.increase_speed()  #一轮之后开始提速
        create_fleet(setting, screen, aliens, ship, path)
        #提高等级并更新等级数据
        stats.level += 1
        sb.prep_level()


def hit_scene(setting):
    '''飞船被撞击'''
    sleep(0.5)
    setting.stop = False


def ship_hit(setting, stats, screen, ship, aliens, bullets, sb, path):
    '''响应被外星人撞到的飞船'''
    if stats.ships_left > 0:
        #将ships_left减1
        stats.ships_left -= 1
        #左上角生命数也-1
        sb.prep_ships()
        #把撞击的画面先显示出来不然如果距离太大，就看不来被撞击了
        update_screen(setting,
                      screen,
                      stats,
                      ship,
                      aliens,
                      bullets,
                      sb,
                      play_button=None)
        #暂停游戏，停止游戏刷新
        setting.stop = True
        #清空外星人和子弹列表
        aliens.empty()
        bullets.empty()
        #创建一群新的外星人，并将飞船放到屏幕底端中央
        create_fleet(setting, screen, aliens, ship, path)
        ship.center_ship()
        #死亡画面
        hit_died = threading.Thread(target=hit_scene, args=(setting, ))
        hit_died.start()
    elif stats.ships_left <= 0:
        stats.game_active = False
        pygame.mouse.set_visible(True)  #游戏结束显示光标
      





def check_aliens_bottom(setting, stats, screen, ship, aliens, bullets, sb,
                        path):
    '''检查是否有外星人到达屏幕底端'''
    screen_rect = screen.get_rect()
    for alien in aliens.sprites():
        if alien.rect.bottom >= screen_rect.bottom:
            #像飞船被撞到一样来处理
            ship_hit(setting, stats, screen, ship, aliens, bullets, sb, path)
            break


def check_high_score(stats, sb):
    if stats.score > stats.high_score:
        stats.high_score = stats.score
        sb.prep_high_score()


def update_screen(set_begin, screen, stats, ship, aliens, bullets, sb,
                  play_button):
    '''重新绘制屏幕内容的事件都在这里'''
    screen.fill(set_begin.bg_color)  #填充窗口屏幕（颜色）
    for bullet in bullets.sprites():  #加载所有的子弹
        bullet.draw_bullet()
    ship.blitme()  #加载飞船 先填充颜色再绘制飞船，不然飞船会被覆盖掉
    aliens_copy = copy.copy(aliens)
    aliens_copy.draw(screen)  #加载外星人,编组绘制用draw()
    sb.show_score()
    if not stats.game_active:
        play_button.draw_button()
    pygame.display.flip()  #让最近绘制的屏幕可见
